<template>
    <div class="login-box">
        <div class="form-box">
            <div class="title-box">
                <span class="welcome">欢迎登录</span>
                <span class="title">{{ setting.title }}</span>
            </div>
            <div class="login-type" v-if="!isScanCode">
                <div class="type-item" v-for="(item, index) in loginTypes" :key="index" @click="changeLoginType(index)"
                    :class="{ active: item.active }">
                    {{ item.name }}
                </div>
            </div>
            <div class="change-code" @click="changeLoginTypeByScan">
                <a href="JavaScript:void(0)" v-if="!isScanCode" title="扫码登录">
                    <i class="iconfont icon-erweima"></i>
                </a>
                <a href="JavaScript:void(0)" v-else title="账号密码登录">
                    <i class="iconfont icon-yonghu"></i>
                </a>
            </div>
            <!-- 普通登录 -->
            <div class="form-content" v-if="!isScanCode">
                <el-form v-if="activeLoginType.type == 'password'" ref="passwordFormRef" :size="formSize"
                    :model="formData" :rules="rules" label-width="auto" class="my-form">
                    <el-form-item prop="username">
                        <el-input v-model="formData.username" placeholder="请输入用户名/邮箱"></el-input>
                    </el-form-item>
                    <el-form-item prop="password">
                        <el-input v-model="formData.password" placeholder="请输入密码" show-password></el-input>
                    </el-form-item>
                    <el-form-item prop="code">
                        <el-input v-model="formData.code" placeholder="请输入验证码">
                            <template #append>
                                <div class="dzs-code-box">
                                    <dzs-identifying-code-canvans v-model:value="locahostCode"
                                        ref="IdentifyingCodeCanvans"></dzs-identifying-code-canvans>
                                </div>
                            </template>
                        </el-input>
                    </el-form-item>
                </el-form>

                <el-form v-else ref="codeFormRef" :size="formSize" :model="formData" :rules="codeRules"
                    label-width="auto" class="my-form">
                    <el-form-item prop="username">
                        <el-input v-model="formData.username" placeholder="请输入用户名/邮箱"></el-input>
                    </el-form-item>
                    <el-form-item prop="code">
                        <el-input v-model="formData.code" placeholder="请输入验证码">
                            <template #append>
                                <dzs-button :disabled="isSendCode" type="primary" @click="getCode(codeFormRef)">
                                    {{ countdown }}
                                </dzs-button>
                            </template>
                        </el-input>
                    </el-form-item>
                </el-form>
            </div>

            <div class="btn-box" v-if="!isScanCode">
                <dzs-button class="btn" type="primary" :size="formSize" :loading="loading"
                    @click="onSubmit">登录</dzs-button>
            </div>
            <div v-if="!isScanCode" class="old-version">
                <a href="https://anran233.com/admin" target="_blank">旧版后台</a>
            </div>

            <!-- 扫码登录 -->
            <div class="scan-code" v-if="isScanCode">
                <div class="scan-code-img">
                    <img :src="codeImgUrl" alt="" v-if="codeImgUrl">
                    <div class="scan-code-expire" v-if="isScanCodeExpire" @click="getScanCode">点击重新获取二维码</div>
                </div>
                <div class="scan-code-text">请使用手机微信扫码登录</div>
            </div>
        </div>
    </div>
</template>
<script setup lang="ts">
import set from "./setting";
import request from "./request/index";
import { ref, computed, reactive, onMounted } from "vue";
import tool from './utils';
import type { ComponentSize, FormInstance, FormRules } from 'element-plus';
import dzsIdentifyingCodeCanvans, { type dzsIdentifyingCodeCanvansInstance } from './components/dzs-identifying-code-canvans';
import { ElMessage } from 'element-plus';
const passwordFormRef = ref<FormInstance>()
const codeFormRef = ref<FormInstance>()
const setting = ref(set);
const formSize = ref<ComponentSize>('large')
const loading = ref(false);
const countdown = ref("获取验证码");
const myDefaultCountdown = 60;
const defaultCountdown = ref(myDefaultCountdown); // 默认验证码倒计时
const isSendCode = ref(false); // 是否发送验证码
const isScanCode = ref(false); // 是否扫码登录
const isScanCodeExpire = ref(false); // 是否扫码登录过期
const locahostCode = ref(""); // 本地验证码
const codeImgUrl = ref("");
const codeTime = ref(0);
const IdentifyingCodeCanvans = ref<dzsIdentifyingCodeCanvansInstance>();
const redirect = ref('/');//重定向地址

onMounted(() => {
    tool.setRootColor(setting.value.ThemeColor, 'theme-color');
    tool.setRootColor(setting.value.fontColor, 'font-color');

    tool.getUrlParam("redirect") && (redirect.value = decodeURIComponent(tool.getUrlParam("redirect")));
    //监听回车事件
    document.onkeydown = function (e: KeyboardEvent) {
        if (e.keyCode == 13 && !isScanCode.value && formData.value.username && formData.value.code) {
            onSubmit();
        }
    }
});

/**登录方式*/
type LoginType = {
    name: string,
    active: boolean,
    method?: string,
    type: "password" | "code"
};

const loginTypes = ref<LoginType[]>([
    {
        name: "账号密码",
        active: true,
        method: "passwordSubmit",
        type: "password"
    },
    {
        name: "邮箱验证码",
        active: false,
        method: "phoneSubmit",
        type: "code"
    },
])

const activeLoginType = computed(() => {
    return loginTypes.value.find(item => item.active) as LoginType;
})
type formData = {
    username: string,
    password: string,
    code: string
}

const formData = ref<formData>({
    username: "",
    password: "",
    code: ""
})

const rules = reactive<FormRules<formData>>({
    username: [
        {
            required: true,
            message: '请输入用户名/邮箱',
            trigger: 'blur'
        },
    ],
    password: [
        {
            required: true,
            message: '请输入密码',
        }
    ],
    code: [
        {
            required: true,
            message: '请输入验证码',
        },
        {
            validator(rule: any, value: string, callback: Function) {
                if (value.toLocaleUpperCase() !== locahostCode.value.toLocaleUpperCase()) {
                    loading.value = false;
                    callback(new Error('验证码错误'));
                } else {
                    callback();
                }
            }
        }
    ]
})

let RulesByCode = [
    {
        required: true,
        message: '请输入验证码',
    }
]

const codeRules = reactive<FormRules<formData>>({
    username: [
        {
            required: true,
            message: '请输入邮箱',
            trigger: 'blur'
        },
        {
            pattern: /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
            message: '请输入正确的邮箱',
            trigger: 'blur'
        }
    ],
    code: RulesByCode
})

/**切换登录方式*/
const changeLoginType = (index: number) => {
    loginTypes.value.forEach((item, i) => {
        item.active = i === index;
    })
    formData.value.password = "";
    formData.value.code = "";
}

/**获取验证码*/
const getCode = async (formEl: FormInstance | undefined) => {
    if (!formEl) return;
    codeRules.code = [];
    await formEl.validate((valid, fields) => {
        if (valid) {
            request({
                url: "/api/email/getCodeByEmail",
                data: {
                    email: formData.value.username,
                    type: "admin"
                },
                success(res) {
                    countdown.value = `${defaultCountdown.value}s后重试`;
                    isSendCode.value = true;
                    let timer = setInterval(() => {
                        if (defaultCountdown.value <= 0) {
                            clearInterval(timer);
                            countdown.value = "获取验证码";
                            isSendCode.value = false;
                            defaultCountdown.value = myDefaultCountdown;
                        } else {
                            countdown.value = `${--defaultCountdown.value}s后重试`;
                        }
                    }, 1000)
                }
            })
        }
    })
}

/**获取登录小程序太阳码*/
const getScanCode = async () => {
    codeTime.value = new Date().getTime();
    request({
        url: "/api/weixin/getUnlimitedQRCode",
        method: "post",
        data: {
            data: `code=${codeTime.value}&admin=true`
        },
        success(res) {
            codeImgUrl.value = res.body;
            codeRules.code = RulesByCode;
            countdownFn();
        }
    })
}

/**倒计时*/
const countdownFn = () => {
    isScanCodeExpire.value = false;
    let timer = setInterval(() => {
        if (defaultCountdown.value <= 0) {
            clearInterval(timer);
            isScanCodeExpire.value = true;
            defaultCountdown.value = myDefaultCountdown;
        } else {
            --defaultCountdown.value;
            // 获取扫码情况
            request({
                url: "/api/v2/users/getScanLoginResult",
                method: "post",
                data: {
                    code: codeTime.value
                },
                success(res) {
                    if (res.type == 1) {
                        clearInterval(timer);
                        goToAuthRedirect();
                    }
                    if (res.type == -1) {
                        clearInterval(timer);
                        defaultCountdown.value = 0;
                    }
                }
            })
        }
    }, 2000)
}

/**改变登录方式 扫码/密码*/
const changeLoginTypeByScan = () => {
    isScanCode.value = !isScanCode.value;
    if (isScanCode.value) {
        getScanCode();
    } else {
        formData.value.username = "";
        formData.value.code = "";
    }
}

/**提交*/
const onSubmit = () => {
    loading.value = true;
    if (activeLoginType.value.type === "password") {
        passwordSubmit()
    } else {
        codeSubmit()
    }
}

/**账号密码登录*/
const passwordSubmit = () => {
    passwordFormRef.value?.validate(async (valid, fields) => {
        if (valid) {
            const params = {
                user: tool.crypto.ACEencrypt({
                    word: {
                        username: formData.value.username,
                        password: formData.value.password
                    }
                }),
                password: tool.crypto.ACEencrypt(formData.value.code),
                code: formData.value.code,
                ua: tool.userAgent()
            }
            request({
                url: "/api/v2/users/adminLogin",
                method: "post",
                data: params,
                success(res) {
                    goToAuthRedirect();
                },
                fail(err) {
                    IdentifyingCodeCanvans.value?.generateCode();
                    loading.value = false;
                }
            })
        }
    })
}

/**验证码登录*/
const codeSubmit = () => {
    codeRules.code = RulesByCode;
    codeFormRef.value?.validate(async (valid, fields) => {
        if (valid) {
            request({
                url: "/api/v2/users/adminLoginByCode",
                method: "post",
                data: {
                    email: formData.value.username,
                    code: formData.value.code
                },
                success(res) {
                    goToAuthRedirect();
                }
            })
        }
    })
}

/**获取用户信息*/
const goToAuthRedirect = () => {
    loading.value = false;
    ElMessage.success("登录成功");
    setTimeout(() => {
        window.location.href = '/auth-redirect?redirect=' + encodeURIComponent(redirect.value as string);
    }, 2000)
}

</script>
<style lang="scss" scoped>
@import url("//at.alicdn.com/t/c/font_4658222_jvyo4fe1qfs.css");

.login-box {
    width: 100vm;
    height: 100vh;
    background-image: url("@/assets/images/login-back.jpg");
    background-position: center;
    background-size: 100% 100%;
    position: relative;

    .form-box {
        position: absolute;
        top: 50%;
        left: 25%;
        transform: translate(-50%, -50%);
        width: 400px;
        padding: 50px;
        background-color: rgba(255, 255, 255, .8);
        border-radius: 5px;
        overflow: hidden;
        box-shadow: 1px 1px 10px rgba(0, 0, 0, .2);

        .title-box {
            user-select: none;

            .welcome {
                font-size: 24px;
                color: #333;
                font-weight: 600;
            }

            .title {
                font-size: 14px;
                color: #999;
                display: inline-block;
                padding-left: 5px;
            }
        }

        .login-type {
            display: flex;
            padding-top: 20px;
            align-items: flex-end;
            user-select: none;

            .type-item {
                padding: 0 20px;
                position: relative;
                cursor: pointer;
                color: #999;
                transition: all .3s;
                height: 20px;

                &.active {
                    color: var(--theme-color);
                    font-size: 16px;
                    font-weight: 600;

                    &::after {
                        content: "";
                        position: absolute;
                        width: 40%;
                        height: 4px;
                        background-color: var(--theme-color);
                        bottom: -10px;
                        left: 50%;
                        transform: translateX(-50%);
                        border-radius: 10px;
                    }
                }

                &:first-child {
                    padding: 0;
                }
            }
        }

        .change-code {
            position: absolute;
            right: 0;
            top: 0;
            border-left: 90px solid transparent;
            border-top: 80px solid #e4e1e1;
            border-bottom: 40px solid transparent;
            cursor: pointer;

            .iconfont {
                font-size: 26px;
                position: absolute;
                top: -70px;
                right: 13px;
                color: #333;
            }
        }

        .dzs-code-box {
            width: 90px;
            height: 40px;
        }

        .scan-code {
            margin-top: 30px;
            text-align: center;

            .scan-code-img {
                width: 240px;
                height: 240px;
                margin: 0 auto;
                position: relative;

                img {
                    width: 100%;
                    height: 100%;
                }

                .scan-code-expire {
                    position: absolute;
                    width: 100%;
                    height: 100%;
                    background-color: rgba(255, 255, 255, 7);
                    line-height: 240px;
                    user-select: none;
                    cursor: pointer;
                    top: 0;
                }
            }

            .scan-code-text {
                font-size: 14px;
                color: #999;
                margin-top: 18px;
            }

        }

        .form-content {
            padding-top: 30px;
        }

        .btn-box {
            padding-top: 10px;

            .btn {
                width: 100%;
            }
        }
    }
}

.old-version {
    padding-top: 10px;
    text-align: right;

    a {
        color: #999;
    }
}
</style>